//
// This file is part of cpp-lib, a library of C++ functions and classes.
// Cpp-lib is copyright (C) 2004 and onwards, The CPL Interest Group.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library (see the file COPYING); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
// 02111-1307  USA
//
// $Id$
//

#ifndef CPP_LIB_REGISTRY_CRYPT_H
#define CPP_LIB_REGISTRY_CRYPT_H

#include <string>
#include <stdexcept>

#include "cpp-lib/registry.h"
#include "cpp-lib/crypt_stream.h"
#include "cpp-lib/util.h"


namespace cpl {

namespace util {

//
// Read a registry in encrypted or plaintext form.
//
// First tries to open the file name + suffix and to read it as
// CFB mode (see cfb_istreambuf).
//
// If this fails, tries to open the file name and to read it as
// plaintext.
//
// In both cases, the registry is read with grammar g and the given
// throw_on_redifinition flag.
//

template< typename BC >
void read_encrypted_configuration(
  registry                 & reg  ,
  BC                       & bc   ,
  std::vector< char > const& iv   ,
  std::string         const& name ,
  std::string         const& suffix                = ".crypt"  ,
  grammar             const& g                     = grammar() ,
  bool                const  throw_on_redefinition = true
) {

  using namespace cpl::util::file ;

  std::auto_ptr< std::istream > is ;

  try {

    std::string const cname = name + suffix ;
    is = cpl::crypt::open_read( bc , iv , cname ) ;

    lexer lex( *is , cname ) ;

    reg.read_from( lex , g , throw_on_redefinition ) ;

  } catch( std::exception const& e ) {

    // didn't work, try unencrypted...

    try
    { reg.read_from( name , g , throw_on_redefinition ) ; }
    catch( std::exception const& f ) {

      // both didn't work, report.

      throw std::runtime_error(
          std::string( "read encrypted configuration: " )
        + e.what()
        + "; plaintext configuration: "
        + f.what()
      ) ;

    }

  }

}

} // namespace util

} // namespace cpl

#endif // CPP_LIB_REGISTRY_CRYPT_H
